package com.example.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.service.GoodsService;
import com.example.service.OrderService;
import com.example.utils.*;
import com.example.wxpay.WxPayJsConfig;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author: xxx
 * @create: 2021/3/18 15:16
 */
@RestController
@RequestMapping("/wxPay")
public class WxPayController {
    private static final Logger logger = LoggerFactory.getLogger(WxPayController.class);

    @Autowired
    private WxPayJsConfig config;
    @Autowired
    private OrderService orderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private RestTemplate restTemplate;
    //存入reis的超时时间
    public static final Long REDIS_TIMEOUT = 1L;

    /**
     * @param request
     * @description: 商品下单
     * @return: com.yunhe.zzedu.common.entity.Result
     * @author: xxx
     * @time: 2021/7/3 10:24
     */
    @RequestMapping("/unifiedOrderH5")
    @Transactional(rollbackFor = Exception.class)
    public Result unifiedMemberOrderJSAPI(HttpServletRequest request) {

        try {
            //生成订单并返回订单信息
            Map<String, Object> mapOrder = new HashMap<>();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            String id = OrderUtil.getOrderNoByUUID();
            mapOrder.put("id", id);
            mapOrder.put("userId", "1");
            mapOrder.put("source", "H5");
            mapOrder.put("sfprice", "0.01");
            mapOrder.put("type", "1");
            mapOrder.put("orderNumber", simpleDateFormat.format(new Date()));
            mapOrder.put("payType", "待支付");
            mapOrder.put("payMethod", "微信支付");
            mapOrder.put("orderType", "已提交");
            mapOrder.put("goodsName", "测试");
            goodsService.saveOrderAdd(mapOrder);
            // 2、开始微信支付统一下单
            return unifiedOrderH5(mapOrder, request);//系统通用的返回结果集，见文章末尾

        } catch (Exception e) {
            logger.error(e.getMessage());
            return ResultUtil.error("运行异常，请联系管理员");
        }
    }

    @RequestMapping("/unifiedOrderJSAPI")
    public Result unifiedOrderJSAPI(HttpServletRequest request, @RequestBody Map<String, Object> map) {

        try {
            Map<String, Object> orderMap = orderService.getOrderAddByGoodsAddId(map);
            if (orderMap != null) {
                // 2、开始微信支付统一下单
                return unifiedOrderJSAPI(orderMap, request);//系统通用的返回结果集，见文章末尾
            } else {
                String openid = null;
                String key = "wx:openid:"+TokenTool.getUserId();
                if (redisTemplate.opsForValue().get(key) != null) {
                    openid = redisTemplate.opsForValue().get(key).toString();
                }
                if (!StringUtils.isNotBlank(openid)){
                    return ResultUtil.error(-500,"请先获取openid");
                }
                Map<String, Object> goodsMap = goodsService.getGoodsAddedById(map);
                //1、生成订单信息
                Map<String, Object> mapOrder = new HashMap<>();
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
                String id = OrderUtil.getOrderNoByUUID();
                mapOrder.put("id", id);
                mapOrder.put("userId", goodsMap.get("userId"));
                mapOrder.put("source", "JSAPI");
                mapOrder.put("sfprice", goodsMap.get("je"));
                mapOrder.put("type", "1");
                mapOrder.put("orderNumber", simpleDateFormat.format(new Date()));
                mapOrder.put("payType", "待支付");
                mapOrder.put("payMethod", "微信支付");
                mapOrder.put("orderType", "已提交");
                mapOrder.put("openId", openid);
                mapOrder.put("goodsId", goodsMap.get("goodsId"));
                mapOrder.put("goodsName", goodsMap.get("goodsName"));
                mapOrder.put("goodsAddId", goodsMap.get("id"));
                goodsService.saveOrderAdd(mapOrder);
                // 2、开始微信支付统一下单
                return unifiedOrderJSAPI(mapOrder, request);//系统通用的返回结果集，见文章末尾
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            return ResultUtil.error("运行异常，请联系管理员");
        }
    }

    /**
     * @param orderMap
     * @param request
     * @description: 微信支付统一下单
     * @return: com.yunhe.zzedu.service.pay.ResultMap
     * @author: xxx
     * @time: 2021/3/18 16:10
     */
    public Result unifiedOrderH5(Map<String, Object> orderMap, HttpServletRequest request) {
        Map<String, String> data = new HashMap<>();
        String orderNo = null;
        try {
            //如果订单不为空
            if (orderMap != null) {
                orderNo = orderMap.get("id").toString();
                Double amount = Double.parseDouble(orderMap.get("sfprice").toString());
                //支付参数
                WXPay wxpay = new WXPay(config);//统一下单接口
                data.put("device_info", "WEB"); //设备号 PC网页或公众号内支付可以传"WEB"
                data.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
                data.put("body", orderMap.get("goodsName").toString()); //商品描述
                data.put("out_trade_no", orderNo); //商户订单号
                data.put("total_fee", String.valueOf((int) (amount * 100))); //标价金额 单位是分
                data.put("spbill_create_ip", getIpAddress(request)); //用户的客户端IP
                data.put("notify_url", config.getWxPayNotifyUrl()); //通知地址
                data.put("trade_type", "MWEB");  // 交易类型  JSAPI--JSAPI支付（或小程序支付）、NATIVE--Native支付、APP--app支付，MWEB--H5支付

                Map<String, String> resp = wxpay.unifiedOrder(data);
                System.out.println("需要请求的地址：" + resp.toString());
                System.out.println("需要请求的地址：" + resp.get("mweb_url"));

                //重定向页面
                return ResultUtil.success(resp.toString());
            } else {
                return ResultUtil.error("微信支付统一下单失败");
            }
        } catch (Exception e) {
            e.getStackTrace();
            logger.error("订单号：{}，错误信息：{}", orderNo, e.getStackTrace());
            return ResultUtil.error("微信支付统一下单失败");
        }
    }

    public Result unifiedOrderJSAPINew(Map<String, Object> orderMap, HttpServletRequest request) {
        Map<String, String> data = new HashMap<>();
        String orderNo = null;
        try {
            //如果订单不为空
            if (orderMap != null) {
                orderNo = orderMap.get("id").toString();
                Double amount = Double.parseDouble(orderMap.get("sfprice").toString()) * 100;
                //支付参数
                RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory());
                String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5";
                Map<String, Object> wxpayMap = new HashMap<>();
                wxpayMap.put("appid", config.getAppID());
                wxpayMap.put("mchid", config.getMchID());
                wxpayMap.put("description", "测试");
                wxpayMap.put("out_trade_no", orderNo);
                Map<String, Object> amountMap = new HashMap<>();
                int intValue = (int) Math.round(amount);
                amountMap.put("total", intValue);
                amountMap.put("currency", "CNY");
                wxpayMap.put("amount", amountMap);

                Map<String, Object> sceneInfoMap = new HashMap<>();
                Map<String, Object> h5InfoMap = new HashMap<>();
                h5InfoMap.put("type", "Wap");
                sceneInfoMap.put("h5_info", h5InfoMap);
                sceneInfoMap.put("payer_client_ip", getIpAddress(request));
                wxpayMap.put("scene_info", sceneInfoMap);
                wxpayMap.put("notify_url", config.getWxPayNotifyUrl());
                Map<String, Object> openidMap = new HashMap<>();
                openidMap.put("openid", "olbGd55tYGnv4uxCX7J3tWTaRiEM");
                wxpayMap.put("payer", openidMap); //openId
                ResponseEntity<JSONObject> forEntity = restTemplate.postForEntity(url, wxpayMap, JSONObject.class);
                System.out.println("forEntity" + forEntity);
                //重定向页面
                return ResultUtil.success(forEntity);
            } else {
                return ResultUtil.error("微信支付统一下单失败");
            }
        } catch (Exception e) {
            e.getStackTrace();
            logger.error("订单号：{}，错误信息：{}", orderNo, e.getStackTrace());
            return ResultUtil.error("微信支付统一下单失败");
        }
    }

    public Result unifiedOrderJSAPI(Map<String, Object> orderMap, HttpServletRequest request) {

        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> data = new HashMap<>();
        String orderNo = null;
        try {
            //如果订单不为空
            if (orderMap != null) {
                orderNo = orderMap.get("id").toString();
                Double amount = Double.parseDouble(orderMap.get("sfprice").toString());

                //支付参数
                WXPay wxpay = new WXPay(config);

                data.put("appid", config.getAppID());
                data.put("secret", config.getSecret());
                data.put("body", "订单支付");
                data.put("mch_id", config.getMchID());
                data.put("notify_url", config.getWxPayNotifyUrl());//异步通知地址（请注意必须是外网）
                data.put("out_trade_no", orderNo);
                data.put("spbill_create_ip", getIpAddress(request)); //自己的服务器IP地址
                data.put("openid", orderMap.get("openId").toString()); //openId

                data.put("total_fee", String.valueOf((int) (amount * 100)));
                data.put("trade_type", "JSAPI");//交易类型JSAPI支付
                String s = WXPayUtil.generateSignature(data, config.getKey());  //签名
                data.put("sign", s);//签名
                //使用官方API请求预付订单
                Map<String, String> resultMap = wxpay.unifiedOrder(data);
                //获取返回码
                String returnCode = resultMap.get("return_code");
                //若返回码为SUCCESS，则会返回一个result_code,再对该result_code进行判断
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = resultMap.get("result_code");
                    if ("SUCCESS".equals(resultCode)) {
                        responseMap = resultMap;
                    }
                }
                if (responseMap == null || responseMap.isEmpty()) {
                    return ResultUtil.error("获取预支付交易会话标识失败" + responseMap);
                }
                // 3、签名生成算法
                Long time = System.currentTimeMillis() / 1000;
                String timestamp = time.toString();
                returnMap.put("appId", config.getAppID());
                returnMap.put("nonceStr", responseMap.get("nonce_str"));
                returnMap.put("package", "prepay_id=" + responseMap.get("prepay_id"));
                returnMap.put("signType", "MD5");
                returnMap.put("timeStamp", timestamp);
                returnMap.put("paySign", WXPayUtil.generateSignature(returnMap, config.getKey()));//微信支付签名
                returnMap.put("sfprice", orderMap.get("sfprice").toString());//微信支付签名

            }
            return ResultUtil.success(returnMap);
        } catch (Exception e) {
            logger.error("订单号：{}，错误信息：{}", orderNo, e.getStackTrace());
            return ResultUtil.error("微信支付统一下单失败");
        }
    }

    /**
     * @param request
     * @description: 微信支付异步通知(JSAPI支付回调)
     * @return: java.lang.String
     * @author: xxx
     * @time: 2021/3/18 16:13
     */
    @RequestMapping(value = "/wxnotify")
    @Transactional(rollbackFor = Exception.class)
    public String wxPayNotify(HttpServletRequest request, HttpServletResponse response) {

        InputStream is = null;
        String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";
        try {
            is = request.getInputStream();
            // 将InputStream转换成String
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            xmlBack = wxPayBack(sb.toString());
            // 告诉微信服务器收到信息了，不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
            response.getWriter().write(xmlBack);
        } catch (Exception e) {
            logger.error("微信手机支付回调通知失败：", e);
        }
        return null;
    }

    /**
     * @param notifyData 异步通知后的XML数据(JSAPI支付回调)
     * @return
     */
    public String wxPayBack(String notifyData) {
        WXPay wxpay = new WXPay(config);
        return back(notifyData, wxpay);
    }

    public String back(String notifyData, WXPay wxpay) {
        String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";
        Map<String, String> notifyMap = new HashMap<>();
        try {
            notifyMap = WXPayUtil.xmlToMap(notifyData);         // 调用官方SDK转换成map类型数据
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//验证签名是否有效，有效则进一步处理

                String return_code = notifyMap.get("return_code");//状态
                String out_trade_no = notifyMap.get("out_trade_no");//商户订单号
                String total_fee = notifyMap.get("total_fee");//订单总金额，单位为分
                if (return_code.equals("SUCCESS")) {
                    if (out_trade_no != null) {
                        // 查询订单是否存在
                        Map<String, Object> order = orderService.getOrderAddById(out_trade_no);
                        if (order != null && order.get("payType").equals("待支付")) {
                            Double dprice = Double.parseDouble(order.get("sfprice").toString());
                            Double dtotal_fee = Double.parseDouble(total_fee);
                            System.out.println("dprice==========="+dprice);
                            System.out.println("dtotal_fee==========="+dtotal_fee);
                            BigDecimal dpriceBig = new BigDecimal(dprice).multiply(new BigDecimal(100));
                            BigDecimal dpriceBigNew = dpriceBig.setScale(2, BigDecimal.ROUND_HALF_UP);
                            BigDecimal dtotal_feeBig = new BigDecimal(dtotal_fee);
                            System.out.println("dpriceBigNew==========="+dpriceBigNew);
                            if(dpriceBigNew.compareTo(dtotal_feeBig) == 0){
                                System.out.println("dpriceBigNew===========true");
                            }else{
                                System.out.println("dpriceBigNew===========false");
                            }
                            System.out.println("dpriceBig==========="+dpriceBig);
                            System.out.println("dtotal_feeBig==========="+dtotal_feeBig);
                            // 校验返回的订单金额是否与商户侧的订单金额一致
//                            if (dpriceBig == dtotal_feeBig) {
                                //业务数据持久化
                                Map<String, Object> map = new HashMap<>();
                                map.put("id", out_trade_no);
                                map.put("payType", "已支付");
                                map.put("payTime", notifyMap.get("time_end"));
                                map.put("wxPayId", notifyMap.get("transaction_id"));
                                // 更新支付状态
                                System.out.println("更新支付状态");
                                updateBack(map, order);
                                logger.info("微信支付回调成功订单号:{}", out_trade_no);
                                xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//                            } else {
//                                logger.info("非法的请求:{}", out_trade_no);
//                                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
//                            }
                        } else {
                            logger.info("订单有问题:{}", out_trade_no);
                            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                        }
                    } else {
                        logger.info("微信支付回调失败订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                    }
                }
                return xmlBack;
            } else {
                // 签名错误，如果数据里没有sign字段，也认为是签名错误
                //失败的数据要不要存储？
                logger.error("微信支付回调通知签名错误");
                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return xmlBack;
            }
        } catch (Exception e) {
            logger.error("微信支付回调通知失败", e);
            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        return xmlBack;
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    @RequestMapping("/weixinInfo")
    public Result weixinInfo(@RequestBody Map<String, Object> param) {
        try {
            //1、获取AccessToken jsapi_ticket
            Map<String, String> tokenMap = tokenMap();
            String accessToken = tokenMap.get("accessToken");
            String jsapiTicket = tokenMap.get("ticket");
            //2、时间戳和随机字符串
            String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
            //3、获取url
            String url = config.getUrl();
            //4、将参数排序并拼接字符串
            String str = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + param.get("url");
            logger.info("参数拼接的字符串：" + str);
            //5、将字符串进行sha1加密
            String signature = SHA1(str);
            logger.info("签名：" + signature);
            Map<String, Object> data = new HashMap<>();
            data.put("timestamp", timestamp);
            data.put("nonceStr", noncestr);
            data.put("signature", signature);
            data.put("accessToken", accessToken);
            data.put("appId", config.getAppID());
            return ResultUtil.success(data);
        } catch (Exception e) {
            logger.error("获取微信信息的错误", e);
            return ResultUtil.error("获取微信信息的错误");
        }

    }

    public String getAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + "&appid=" + config.getAppID() + "&secret=" + config.getSecret();
        ResponseEntity<String> res = restTemplate.getForEntity(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(res.getBody());
        String accessToken = jsonObject.getString("access_token");
        redisTemplate.opsForValue().set("accessToken", accessToken, 2L, TimeUnit.HOURS);
        return accessToken;
    }

    public String getTicket(String accessToken) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";// 这个url链接和参数不能变
        ResponseEntity<String> res = restTemplate.getForEntity(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(res.getBody());
        String ticket = jsonObject.getString("ticket");
        redisTemplate.opsForValue().set("ticket", ticket, 2L, TimeUnit.HOURS);
        return ticket;
    }

    public Map<String, String> tokenMap() {
        Map<String, String> tokenMap = new HashMap<>();
        String accessToken = null;
        String ticket = null;
        if (redisTemplate.opsForValue().get("access_token") != null) {
            accessToken = redisTemplate.opsForValue().get("access_token").toString();
        } else {
            accessToken = getAccessToken();
        }
        if (redisTemplate.opsForValue().get("ticket") != null) {
            ticket = redisTemplate.opsForValue().get("ticket").toString();
        } else {
            ticket = getTicket(accessToken);
        }
        tokenMap.put("accessToken", accessToken);
        tokenMap.put("ticket", ticket);
        return tokenMap;
    }

    public static String SHA1(String decript) {
        try {
            MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            logger.error("SHA1发生错误", e);
        }
        return "";
    }

    public void updateBack(Map<String, Object> map, Map<String, Object> order) {
        orderService.updateOrderAdd(map);
        String type = order.get("type").toString();
        switch (type) {
            case "1":
                Map<String, Object> mapId = new HashMap<>();
                mapId.put("id", order.get("goodsAddId").toString());
                Map<String, Object> mapGoodsAdded = goodsService.getGoodsAddedById(mapId);
                Map<String, Object> mapGoodsId = new HashMap<>();
                mapGoodsId.put("id", mapGoodsAdded.get("goodsId"));
                Map<String, Object> mapGoods = goodsService.getById(mapGoodsId);
                if (mapGoodsAdded.get("status").toString().equals("1")) {
                    if (mapGoods.get("added").toString().equals("4")) {
                        Map<String, Object> mapNew = new HashMap<>();
                        mapNew.put("id", mapGoods.get("id"));
                        mapNew.put("added", 1);
                        mapNew.put("price", mapGoods.get("newPrice").toString());
                        goodsService.update(mapNew);//上架
                        mapId.put("status", 2);
                        goodsService.updateGoodsAdded(mapId);//更新申请状态
                        //保存购买记录
                        Map<String, Object> orderAddLog = new HashMap<>();
                        orderAddLog.put("id", IDTool.getUUID32());
                        orderAddLog.put("orderId", order.get("id"));
                        orderAddLog.put("userId", order.get("userId"));
                        orderAddLog.put("goodsId", order.get("goodsId"));
                        orderAddLog.put("buyTime", map.get("payTime"));
                        orderService.saveOrderAddLog(orderAddLog);
                    } else {
                        System.out.println("商品状态不符合上架条件");
                    }
                } else {
                    System.out.println("已审核过");
                }
                break;
            default:
                break;
        }

    }
    @RequestMapping("/getOpenIdNew")
    public Result getOpenIdNew(@RequestBody Map<String, Object> map) {
        // 第二步：通过code换取网页授权access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + config.getAppID() +
                "&secret=" + config.getSecret() +
                "&code=" + map.get("code") +
                "&grant_type=authorization_code";

        ResponseEntity<String> res = restTemplate.getForEntity(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(res.getBody());
        System.out.println(jsonObject.toString());
        String openid = null;
        if (jsonObject.get("openid") != null && StringUtils.isNotBlank(jsonObject.get("openid").toString())) {
            openid = jsonObject.get("openid").toString();
            String key = "wx:openid:"+TokenTool.getUserId();
            redisTemplate.opsForValue().set(key, openid);
            return ResultUtil.success();
        } else {
            return ResultUtil.error(-500, jsonObject.toString());
        }
    }

}